package com.macro.mall.service.impl;

import com.github.pagehelper.PageHelper;
import com.macro.mall.common.api.CommonPage;
import com.macro.mall.common.api.CommonResult;
import com.macro.mall.common.api.ResultCode;
import com.macro.mall.dao.DistributionOrderDao;
import com.macro.mall.dao.OmsDistributionStoreOrderDao;
import com.macro.mall.dao.PortalOrderDao;
import com.macro.mall.dao.WithdrawalApplyDao;
import com.macro.mall.dto.UmsAdminDTO;
import com.macro.mall.dto.UmsWithdrawalApplyDto;
import com.macro.mall.mapper.UmsMemberMapper;
import com.macro.mall.mapper.UmsStoreMapper;
import com.macro.mall.mapper.UmsWithdrawalApplyMapper;
import com.macro.mall.model.*;
import com.macro.mall.service.UmsAdminService;
import com.macro.mall.service.UmsWithdrawalApplyService;
import com.macro.mall.wx.service.WithdrawalService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class UmsWithdrawalApplyServiceImpl implements UmsWithdrawalApplyService {
    @Autowired
    private UmsWithdrawalApplyMapper withdrawalApplyMapper;
    @Autowired
    private UmsAdminService umsAdminService;
    @Autowired
    private WithdrawalApplyDao applyDao;
    @Autowired
    private DistributionOrderDao distributionOrderDao;
    @Autowired
    private OmsDistributionStoreOrderDao distributionStoreOrderDao;

    @Autowired
    private WithdrawalService withdrawalService;

    @Autowired
    private WithdrawalApplyDao withdrawalApplyDao;
    @Autowired
    private UmsStoreMapper umsStoreMapper;
    @Autowired
    private UmsWithdrawalApplyMapper umsWithdrawalApplyMapper;
    @Autowired
    private UmsMemberMapper memberMapper;


    @Override
    public CommonResult<CommonPage<UmsWithdrawalApply>> getMemberWithdrawalList(String userName, UmsWithdrawalApplyDto queryParam, Integer pageNum, Integer pageSize) throws ParseException {
        PageHelper.startPage(pageNum, pageSize);
        UmsWithdrawalApplyExample example = new UmsWithdrawalApplyExample();
        UmsWithdrawalApplyExample.Criteria criteria = example.createCriteria().andAdminUserNameEqualTo(userName);
        if (queryParam != null) {
            if (queryParam.getStatus() != null) {
                criteria.andStatusEqualTo(queryParam.getStatus());
            }
            if (queryParam.getMemberId() != null) {
                criteria.andMemberIdEqualTo(queryParam.getMemberId());
            }
            if (queryParam.getStarteDate() != null && queryParam.getEndDate() != null) {
                //开始日期以当天0点处理，结束时间以当天23点59分59秒处理
                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
                Date statDate = sdf.parse(sdf.format(queryParam.getStarteDate()).substring(0, 8)+ "000000");
                Date endDate = sdf.parse(sdf.format(queryParam.getEndDate()).substring(0, 8)+ "235959");
                criteria.andCreateTimeBetween(statDate, endDate);
            }
        }
        //提现类型：0->佣金提现（针对经纪人提现佣金）;
        criteria.andTypeEqualTo(0);
        example.setOrderByClause("create_time desc");
        List<UmsWithdrawalApply> umsWithdrawalApplies = this.withdrawalApplyMapper.selectByExample(example);
        return CommonResult.success(CommonPage.restPage(umsWithdrawalApplies));
    }

    @Transactional
    @Override
    public CommonResult agreeOrRefuse(String userName, Long id, Integer type, String reason, String ip) {
        CommonResult result = CommonResult.failed("请求失败，请稍后再试");
        UmsWithdrawalApply apply = this.withdrawalApplyMapper.selectByPrimaryKey(id);
        UmsAdmin admin = this.umsAdminService.getAdminByUsername(userName);
        if (type.equals(0)) {
            if (apply != null) {
                Long memberId = apply.getMemberId();
                UmsMember member = memberMapper.selectByPrimaryKey(memberId);
                //获取当前分销商的已结算
                BigDecimal alreadyTotalCommission = distributionOrderDao.getTotalCommission(memberId, 6);
                if (alreadyTotalCommission == null) {
                    return CommonResult.failed("已结算金额为空");
                }
                this.distributionOrderDao.getTotalCommission(memberId, 6);
                //用户已经提现的总金额
                BigDecimal hasWithdrawalCommission = this.applyDao.getHasWithdrawalCommission(memberId, null, null);
                if (hasWithdrawalCommission == null) {
                    hasWithdrawalCommission = BigDecimal.ZERO;
                }
                //用户可提现的佣金总额
                BigDecimal totalCommission = alreadyTotalCommission.subtract(hasWithdrawalCommission);
                if (totalCommission.compareTo(apply.getAmount()) >= 0) {
                    if (StringUtils.isNotBlank(member.getOpenId())) {
                        apply.setStatus(10);//最终状态
                        apply.setOperateUserName(userName);
                        apply.setOperateUserId(admin.getId());
                        apply.setUpdateTime(new Date());
                        int i = this.withdrawalApplyMapper.updateByPrimaryKey(apply);
                        if (i > 0) {
                            try {
                                CommonResult withdrawal = this.withdrawalService.withdrawal(apply.getAmount(), member.getOpenId(), ip);
                                if (withdrawal.getCode() == ResultCode.SUCCESS.getCode()) {
                                    return withdrawal;
                                } else {
                                    throw new RuntimeException(withdrawal.getMessage());
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                                throw new RuntimeException("提现失败，请稍后再试");
                            }
                        } else {
                            throw new RuntimeException("提现失败，请稍后再试");
                        }
                    } else {
                        result = CommonResult.failed("超过提现最大限额:" + totalCommission + "元");
                    }
                } else {
                    result = CommonResult.failed("超过提现最大限额:" + totalCommission + "元");
                }
            }
        } else {
            apply.setStatus(15);
            apply.setOperateUserName(userName);
            apply.setOperateUserId(admin.getId());
            apply.setUpdateTime(new Date());
            apply.setFailedReason(reason);
            int i = this.withdrawalApplyMapper.updateByPrimaryKey(apply);
            result = CommonResult.success(i);
        }
        return result;
    }


    /**
     * 获取店铺提现记录列表
     *
     * @param currentUserName
     * @param queryParam
     * @return
     */
    @Override
    public CommonResult getStoreApplyList(String currentUserName, UmsWithdrawalApplyDto queryParam) throws ParseException {
        UmsAdminDTO adminDTO = this.umsAdminService.getAdminDTOByUserName(currentUserName);
        PageHelper.startPage(queryParam.getPageNum(), queryParam.getPageSize());
        UmsWithdrawalApplyExample umsWithdrawalApplyExample = new UmsWithdrawalApplyExample();
        UmsWithdrawalApplyExample.Criteria criteria = umsWithdrawalApplyExample.createCriteria();
        if (queryParam != null) {
            if (queryParam.getStatus() != null) {
                criteria.andStatusEqualTo(queryParam.getStatus());
            }
            if (queryParam.getMemberId() != null) {
                criteria.andMemberIdEqualTo(queryParam.getMemberId());
            }
            if (queryParam.getStarteDate() != null && queryParam.getEndDate() != null) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
                Date statDate = sdf.parse(sdf.format(queryParam.getStarteDate()).substring(0, 8)+ "000000");
                Date endDate = sdf.parse(sdf.format(queryParam.getEndDate()).substring(0, 8)+ "235959");
                criteria.andCreateTimeBetween(statDate, endDate);
            }
        }
        if (adminDTO.getAdminType().equals(0)) {
            if(queryParam.getIsAudit()!=null&&queryParam.getIsAudit().equals(0)){
                criteria.andStatusEqualTo(5);
            }
        } else if (adminDTO.getAdminType().equals(2)) {
            criteria.andStoreIdEqualTo(adminDTO.getStoreId());
        } else {
            UmsStoreExample example = new UmsStoreExample();
            example.createCriteria().andParentIdEqualTo(adminDTO.getId());
            List<Long> storeIds = this.umsStoreMapper.selectByExample(example).stream().map(UmsStore::getId).collect(Collectors.toList());
            criteria.andStoreIdIn(storeIds);
        }
        criteria.andTypeEqualTo(1);
        umsWithdrawalApplyExample.setOrderByClause("create_time desc");
        List<UmsWithdrawalApply> umsWithdrawalApplyList = withdrawalApplyMapper.selectByExample(umsWithdrawalApplyExample);
        return CommonResult.success(CommonPage.restPage(umsWithdrawalApplyList));
    }


    /**
     * 查询店铺和经纪人的佣金总额，已提现，可提现金额
     *
     * @param currentUserName
     * @return
     */
    @Override
    public CommonResult getStoreMx(String currentUserName) {
        UmsAdminDTO admin = this.umsAdminService.getAdminDTOByUserName(currentUserName);
        if (admin.getAdminType().equals(2)) {
            List<Map<String, Object>> resultList = new ArrayList<>();
            //获取店铺佣金总额
            BigDecimal total = (BigDecimal) distributionStoreOrderDao.getStoreMx(admin.getStoreId(), null);
            //获取店铺下经纪人总额
            BigDecimal agentTotal = (BigDecimal) distributionOrderDao.getStoreMx(admin.getStoreId(), null);
            agentTotal = nullToZero(agentTotal);
            //获取店铺已提现金额
            BigDecimal txTotal = (BigDecimal) withdrawalApplyDao.getStoreMx(admin.getStoreId(), 10, null);
            txTotal = nullToZero(txTotal);
            //获取经纪人已提现金额
            BigDecimal agentTxTotal = (BigDecimal) withdrawalApplyDao.getStoreMx(admin.getStoreId(), 10, 0);
            agentTxTotal = nullToZero(agentTxTotal);
            //获取经纪人可提现金额
            BigDecimal agentCanTx = null;
//            if(agentTotal!=null&&agentTxTotal!=null){
            agentCanTx = agentTotal.subtract(agentTxTotal);
//            }
            //店铺所有可提现金额
            BigDecimal canTx = null;
            if (!(total == null)) {
                canTx = total.subtract(agentTotal).subtract(txTotal);//js.subtract(tx);
            }else{
                canTx = BigDecimal.ZERO;
            }
            Map<String, Object> returnMap = new HashMap<>();
            returnMap.put("total", total);//总额
            returnMap.put("txTotal", txTotal);//已提现
            returnMap.put("canTx", canTx);//可提现
            returnMap.put("agentTotal",agentTotal);//经纪人总额
            returnMap.put("agentTxTotal",agentTxTotal);//经纪人已提现总额
            returnMap.put("agentCanTx",agentCanTx);//经纪人可提现总额
            returnMap.put("storeId", admin.getStoreId());
            returnMap.put("adminType",admin.getAdminType());
            resultList.add(returnMap);
            return CommonResult.success(resultList);
        } else if (admin.getAdminType().equals(1)) {
            UmsStoreExample example = new UmsStoreExample();
            example.createCriteria().andParentIdEqualTo(admin.getId());
            List<Long> storeIds = this.umsStoreMapper.selectByExample(example).stream().map(UmsStore::getId).collect(Collectors.toList());
            List<Map<String, Object>> resultList = new ArrayList<>();
            storeIds.forEach(p -> {
                //获取店铺总额
                BigDecimal total = (BigDecimal) distributionStoreOrderDao.getStoreMx(p, null);
                total = nullToZero(total);
                //获取店铺下经纪人总额
                BigDecimal agentTotal = (BigDecimal) distributionOrderDao.getStoreMx(p, null);
                agentTotal = nullToZero(agentTotal);
                //获取店铺已提现金额
                BigDecimal txTotal = (BigDecimal) withdrawalApplyDao.getStoreMx(p, 10, null);
                txTotal = nullToZero(txTotal);
                //获取经纪人已提现金额
                BigDecimal agentTxTotal = (BigDecimal) withdrawalApplyDao.getStoreMx(p, 10, 0);
                agentTxTotal = nullToZero(agentTxTotal);
                //获取经纪人可提现金额
                BigDecimal agentCanTx = null;
                if(agentTotal!=null&&agentTxTotal!=null){
                    agentCanTx = agentTotal.subtract(agentTxTotal);
                }
                //店铺所有可提现金额
                BigDecimal canTx = null;
                if (!(total == null) && !(agentTotal == null) && !(txTotal == null)) {
                    canTx = total.subtract(agentTotal).subtract(txTotal);//js.subtract(tx);
                }
                Map<String, Object> returnMap = new HashMap<>();
                returnMap.put("total", total);//总额
                returnMap.put("txTotal", txTotal);//已提现
                returnMap.put("canTx", canTx);//可提现
                returnMap.put("agentTotal",agentTotal);//经纪人总额
                returnMap.put("agentTxTotal",agentTxTotal);//经纪人已提现总额
                returnMap.put("agentCanTx",agentCanTx);//经纪人可提现总额
                returnMap.put("adminType",admin.getAdminType());
                returnMap.put("storeId", p);
                resultList.add(returnMap);
            });
            return CommonResult.success(resultList);
        } else {
            UmsStoreExample example = new UmsStoreExample();
            List<Long> storeIds = this.umsStoreMapper.selectByExample(example).stream().map(UmsStore::getId).collect(Collectors.toList());
            List<Map<String, Object>> resultList = new ArrayList<>();
            storeIds.forEach(p -> {
                BigDecimal total = (BigDecimal) distributionStoreOrderDao.getStoreMx(p, null);
                //获取店铺下经纪人总额
                BigDecimal agentTotal = (BigDecimal) distributionOrderDao.getStoreMx(p, null);
                //获取店铺已提现金额
                BigDecimal txTotal = (BigDecimal) withdrawalApplyDao.getStoreMx(p, 10, 1);
                //获取经纪人已提现金额
                BigDecimal agentTxTotal = (BigDecimal) withdrawalApplyDao.getStoreMx(p, 10, 0);
                //获取经纪人可提现金额
                BigDecimal agentCanTx = null;
                if(agentTotal!=null&&agentTxTotal!=null){
                    agentCanTx = agentTotal.subtract(agentTxTotal);
                }
                //店铺所有可提现金额
                BigDecimal canTx = null;
                if (!(total == null) && !(agentTotal == null) && !(txTotal == null)) {
                    canTx = total.subtract(agentTotal).subtract(txTotal);//js.subtract(tx);
                }
                Map<String, Object> returnMap = new HashMap<>();
                returnMap.put("total", total);//总额
                returnMap.put("txTotal", txTotal);//已提现
                returnMap.put("canTx", canTx);//可提现
                returnMap.put("agentTotal",agentTotal);//经纪人总额
                returnMap.put("agentTxTotal",agentTxTotal);//经纪人已提现总额
                returnMap.put("agentCanTx",agentCanTx);//经纪人可提现总额
                returnMap.put("adminType",admin.getAdminType());
                returnMap.put("storeId", p);
                resultList.add(returnMap);
            });
            return CommonResult.success(resultList);
        }
    }

    /**
     * 平台审核店铺提现申请
     * @param userName
     * @param id
     * @param type
     *          0为同意提现，1为拒绝提现
     * @param reason
     *
     * @return
     */
    @Transactional
    @Override
    public CommonResult audit(String userName, Long id, Integer type, String reason, String ip) {
        CommonResult result = CommonResult.failed("请求失败，请稍后再试");
        UmsWithdrawalApply apply = this.withdrawalApplyMapper.selectByPrimaryKey(id);
        UmsAdmin admin = this.umsAdminService.getAdminByUsername(userName);
        if (type.equals(0)) {
            if (apply != null) {
                Long storeId = apply.getStoreId();
                //获取店铺佣金总额
                BigDecimal total = (BigDecimal) distributionStoreOrderDao.getStoreMx(storeId, null);
                //获取店铺下经纪人总额
                BigDecimal agentTotal = (BigDecimal) distributionOrderDao.getStoreMx(storeId, null);
                //获取店铺已提现金额
                BigDecimal txTotal = (BigDecimal) withdrawalApplyDao.getStoreMx(storeId, 10, null);
                //店铺所有可提现金额
                BigDecimal canTx = null;
                if (!(total == null) && !(agentTotal == null) && !(txTotal == null)) {
                    canTx = total.subtract(agentTotal).subtract(txTotal);//js.subtract(tx);
                }
                if (canTx.compareTo(apply.getAmount()) >= 0) {
                    if (StringUtils.isNotBlank(admin.getOpenId())) {
                        apply.setStatus(10);//最终状态
                        apply.setOperateUserName(userName);
                        apply.setOperateUserId(admin.getId());
                        apply.setUpdateTime(new Date());
                        int i = this.withdrawalApplyMapper.updateByPrimaryKey(apply);
                        if (i > 0) {
                            try {
                                CommonResult withdrawal = this.withdrawalService.withdrawal(apply.getAmount(), admin.getOpenId(), ip);
                                if (withdrawal.getCode() == ResultCode.SUCCESS.getCode()) {
                                    return withdrawal;
                                } else {
                                    throw new RuntimeException(withdrawal.getMessage());
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                                throw new RuntimeException("提现失败，请稍后再试");
                            }
                        } else {
                            throw new RuntimeException("提现失败，请稍后再试");
                        }
                    } else {
                        result = CommonResult.failed("超过提现最大限额:" + canTx + "元");
                    }
                } else {
                    result = CommonResult.failed("超过提现最大限额:" + canTx + "元");
                }
            }
        } else {
            apply.setStatus(20);
            apply.setOperateUserName(userName);
            apply.setOperateUserId(admin.getId());
            apply.setUpdateTime(new Date());
            apply.setFailedReason(reason);
            int i = this.withdrawalApplyMapper.updateByPrimaryKey(apply);
            result = CommonResult.success(i);
        }
        return result;
    }

    /**
     * 新增店铺提现申请
     *
     * @param currentName
     * @param price
     * @return
     */
    @Override
    public CommonResult add(String currentName, BigDecimal price) {
        UmsAdminDTO umsAdminDTO = umsAdminService.getAdminDTOByUserName(currentName);
        //获取店铺佣金总额
        BigDecimal total = (BigDecimal) distributionStoreOrderDao.getStoreMx(umsAdminDTO.getStoreId(), null);
        if (total == null) {
            return CommonResult.failed("暂无可提现金额");
        }
        //获取店铺下经纪人总额
        BigDecimal agentTotal = BigDecimal.ZERO;
        BigDecimal storeMx1 = distributionOrderDao.getStoreMx(umsAdminDTO.getStoreId(), null);
        if(storeMx1!=null){
            agentTotal = storeMx1;
        }
        //获取店铺已提现金额
        BigDecimal txTotal = BigDecimal.ZERO;
        BigDecimal storeMx = withdrawalApplyDao.getStoreMx(umsAdminDTO.getStoreId(), 10, null);
        if(storeMx!=null){
            txTotal = storeMx;
        }
        //店铺所有可提现金额
        BigDecimal canTx = null;
        if (!(total == null)) {
            canTx = total.subtract(agentTotal).subtract(txTotal);//js.subtract(tx);
        }
        if(canTx!=null&&canTx.compareTo(price)>=0){
            UmsWithdrawalApply umsWithdrawalApply = new UmsWithdrawalApply();
            umsWithdrawalApply.setStatus(5);
            umsWithdrawalApply.setAdminId(umsAdminDTO.getId());
            umsWithdrawalApply.setCreateTime(new Date());
            umsWithdrawalApply.setAdminUserName(umsAdminDTO.getUserName());
            umsWithdrawalApply.setAmount(price);
            umsWithdrawalApply.setStoreId(umsAdminDTO.getStoreId());
            umsWithdrawalApply.setType(1);
            umsWithdrawalApplyMapper.insert(umsWithdrawalApply);
            return CommonResult.success("添加成功");
        }else{
            return CommonResult.failed("可提现金额有误，请重新输入！");
        }


    }

    //null转0
    private BigDecimal nullToZero(BigDecimal money){
        if (money == null) {
            return BigDecimal.ZERO;
        }else {
            return money;
        }
    }

}
